import React from 'react';
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import '@testing-library/jest-dom';
import PdfViewer from '../PdfViewer';

// 增加测试超时时间
jest.setTimeout(30000);

// Mock react-pdf components
jest.mock('react-pdf', () => ({
  Document: ({ children, onLoadSuccess }) => {
    // 立即触发onLoadSuccess
    setTimeout(() => {
      onLoadSuccess({ numPages: 10 });
    }, 0);
    return <div data-testid="mock-document">{children}</div>;
  },
  Page: ({ pageNumber, scale, rotate, onLoadSuccess, renderTextLayer, renderAnnotationLayer, children }) => {
    const mockPage = {
      getViewport: ({ scale, rotation }) => ({
        width: 800 * scale,
        height: 1200 * scale,
      }),
    };

    // 立即触发onLoadSuccess
    setTimeout(() => {
      onLoadSuccess(mockPage);
    }, 0);

    return (
      <div
        className="page"
        data-page={pageNumber}
        data-rotate={rotate}
        data-scale={scale}
        data-testid="mock-page"
      >
        {children}
      </div>
    );
  },
  pdfjs: {
    GlobalWorkerOptions: {
      workerSrc: '',
    },
    version: '3.11.174',
  },
}));

// Mock react-konva components
let mockRects = [];
const mockTransformerNode = {
  nodes: jest.fn(),
  getLayer: jest.fn(() => ({ batchDraw: jest.fn() })),
  getStage: jest.fn(() => ({
    findOne: (selector) => {
      const id = selector.replace('#', '');
      return mockRects.find(rect => rect.attrs.id === id);
    }
  }))
};

jest.mock('react-konva', () => {
  return {
    Stage: ({ children, width, height, onMouseDown, onMouseMove, onMouseUp, onClick }) => {
      const mockStage = {
        getStage: () => ({
          getPointerPosition: () => ({ x: 100, y: 100 }),
          findOne: (selector) => {
            const id = selector.replace('#', '');
            return mockRects.find(rect => rect.attrs.id === id);
          }
        }),
      };

      return (
        <div 
          data-testid="mock-stage"
          style={{ width, height }}
          onMouseDown={(e) => {
            e.target = mockStage;
            onMouseDown && onMouseDown(e, 1);
          }}
          onMouseMove={(e) => {
            e.target = mockStage;
            onMouseMove && onMouseMove(e);
          }}
          onMouseUp={(e) => {
            e.target = mockStage;
            onMouseUp && onMouseUp(e);
          }}
          onClick={(e) => {
            e.target = e.currentTarget === e.target ? mockStage : e.target;
            onClick && onClick(e, 1);
          }}
        >
          {children}
        </div>
      );
    },
    Layer: ({ children }) => <div data-testid="mock-layer">{children}</div>,
    Rect: ({ id, x, y, width, height, stroke, strokeWidth, fill, opacity, onClick, draggable, onDragEnd, onTransformEnd }) => {
      const mockRect = {
        attrs: { id },
        x: () => x,
        y: () => y,
        width: () => width,
        height: () => height,
        scaleX: () => 1,
        scaleY: () => 1,
      };
      
      // 将mockRect添加到全局数组中，以便在测试中访问
      if (!mockRects.find(rect => rect.attrs.id === id)) {
        mockRects.push(mockRect);
      }

      return (
        <div
          data-annotation-id={id}
          data-testid="mock-rect"
          style={{
            position: 'absolute',
            left: `${x}px`,
            top: `${y}px`,
            width: `${width}px`,
            height: `${height}px`,
            stroke,
            strokeWidth,
            fill,
            opacity,
          }}
          onClick={(e) => {
            e.target = mockRect;
            e.stopPropagation();
            onClick && onClick(e, 1);
          }}
          draggable={draggable}
          onDragEnd={(e) => {
            e.target = mockRect;
            onDragEnd && onDragEnd(e, 1);
          }}
          onTransformEnd={(e) => {
            e.target = mockRect;
            onTransformEnd && onTransformEnd(e, 1);
          }}
        />
      );
    },
    Transformer: ({ ref, boundBoxFunc, enabledAnchors }) => {
      // 将ref设置为mock值
      if (ref) {
        ref.current = mockTransformerNode;
      }
      return <div data-testid="mock-transformer" />;
    },
  };
});

describe('PdfViewer', () => {
  const mockFile = new File([''], 'test.pdf', { type: 'application/pdf' });
  const mockOnAnnotationChange = jest.fn();

  beforeEach(() => {
    jest.clearAllMocks();
    mockRects = [];
    mockTransformerNode.nodes.mockClear();
  });

  it('renders PDF viewer with initial state', async () => {
    render(
      <PdfViewer
        file={mockFile}
        selectedTool="rectangle"
        onAnnotationChange={mockOnAnnotationChange}
      />
    );

    // 等待页面和Stage加载完成
    await waitFor(() => {
      expect(screen.getByTestId('pdf-viewer')).toBeInTheDocument();
      expect(screen.getByTestId('mock-document')).toBeInTheDocument();
    });
    
    // 确保所有页面加载完毕并渲染出Stage
    await waitFor(() => {
      const stages = screen.getAllByTestId('mock-stage');
      expect(stages.length).toBe(4); // 4页应该可见
    }, { timeout: 3000 });
  });

  it('handles annotation creation', async () => {
    render(
      <PdfViewer
        file={mockFile}
        selectedTool="rectangle"
        onAnnotationChange={mockOnAnnotationChange}
      />
    );

    // 等待Stage加载完成
    await waitFor(() => {
      const stages = screen.getAllByTestId('mock-stage');
      expect(stages.length).toBe(4);
    }, { timeout: 3000 });

    const stages = screen.getAllByTestId('mock-stage');
    const firstStage = stages[0];

    // 模拟创建标注的鼠标事件
    fireEvent.mouseDown(firstStage);
    fireEvent.mouseMove(firstStage);
    fireEvent.mouseUp(firstStage);

    // 等待标注创建完成并检查onAnnotationChange是否被调用
    await waitFor(() => {
      expect(mockOnAnnotationChange).toHaveBeenCalled();
    });

    // 等待Rect渲染
    await waitFor(() => {
      const rects = screen.getAllByTestId('mock-rect');
      expect(rects.length).toBeGreaterThan(0);
    }, { timeout: 3000 });
  });

  it('handles page navigation', async () => {
    render(
      <PdfViewer
        file={mockFile}
        selectedTool="rectangle"
        onAnnotationChange={mockOnAnnotationChange}
      />
    );

    // 等待页面加载完成
    await waitFor(() => {
      expect(screen.getByText('第 1 - 4 页 / 共 10 页')).toBeInTheDocument();
    });

    const nextButton = screen.getByTitle('下一页');
    fireEvent.click(nextButton);

    // 验证页面导航
    await waitFor(() => {
      expect(screen.getByText('第 5 - 8 页 / 共 10 页')).toBeInTheDocument();
    });
  });

  it('handles zoom controls', async () => {
    render(
      <PdfViewer
        file={mockFile}
        selectedTool="rectangle"
        onAnnotationChange={mockOnAnnotationChange}
      />
    );

    await waitFor(() => {
      expect(screen.getByText('100%')).toBeInTheDocument();
    });

    const zoomInButton = screen.getByTitle('放大');
    fireEvent.click(zoomInButton);

    await waitFor(() => {
      expect(screen.getByText('120%')).toBeInTheDocument();
    });

    const zoomOutButton = screen.getByTitle('缩小');
    fireEvent.click(zoomOutButton);

    await waitFor(() => {
      expect(screen.getByText('100%')).toBeInTheDocument();
    });
  });

  it('handles rotation', async () => {
    render(
      <PdfViewer
        file={mockFile}
        selectedTool="rectangle"
        onAnnotationChange={mockOnAnnotationChange}
      />
    );

    await waitFor(() => {
      const pages = screen.getAllByTestId('mock-page');
      expect(pages[0]).toHaveAttribute('data-rotate', '0');
    });

    const rotateButton = screen.getByTitle('旋转');
    fireEvent.click(rotateButton);

    await waitFor(() => {
      const pages = screen.getAllByTestId('mock-page');
      expect(pages[0]).toHaveAttribute('data-rotate', '90');
    });
  });

  it('handles annotation selection and transformer attachment', async () => {
    render(
      <PdfViewer
        file={mockFile}
        selectedTool="mouse"
        onAnnotationChange={mockOnAnnotationChange}
      />
    );

    // 等待Stage加载完成
    await waitFor(() => {
      const stages = screen.getAllByTestId('mock-stage');
      expect(stages.length).toBe(4);
    }, { timeout: 3000 });

    // 首先创建一个标注
    const stages = screen.getAllByTestId('mock-stage');
    
    // 切换到rectangle工具创建标注
    const pdfViewer = screen.getByTestId('pdf-viewer');
    pdfViewer.setAttribute('data-tool', 'rectangle');
    
    fireEvent.mouseDown(stages[0]);
    fireEvent.mouseMove(stages[0]);
    fireEvent.mouseUp(stages[0]);

    // 等待标注创建完成
    await waitFor(() => {
      expect(mockOnAnnotationChange).toHaveBeenCalled();
    });

    // 渲染标注矩形
    await waitFor(() => {
      const rects = screen.getAllByTestId('mock-rect');
      expect(rects.length).toBeGreaterThan(0);
    }, { timeout: 2000 });

    // 切换回mouse工具进行选择
    pdfViewer.setAttribute('data-tool', 'mouse');
    
    // 模拟选择标注
    const rects = screen.getAllByTestId('mock-rect');
    fireEvent.click(rects[0]);

    // 验证Transformer被调用
    await waitFor(() => {
      expect(mockTransformerNode.nodes).toHaveBeenCalled();
    });
  });
}); 